
use std::path::Path;
use std::fs::metadata;
use std::fs;
use std::fs::File;
use serde::{ Deserialize,Serialize};
use crypto::{aes,
    buffer::{RefWriteBuffer,WriteBuffer,ReadBuffer,RefReadBuffer,BufferResult::BufferUnderflow},
    blockmodes,
    symmetriccipher::SymmetricCipherError
};
use std::io::Write;

#[derive(Deserialize,Serialize)]
pub struct Config {
    pub url:String,
    pub sql_type:SqlType
}

#[derive(Deserialize,Serialize)]
pub enum SqlType {
    Mysql,
    Postgres,
    Sqlite
}

const STR_KEY:&str = "HellouiroweuoirujdjdlskjhflajdljafdsfsfsfWorld";
const CONFIG_FILE_NAME:&str = "selfconfig";

pub async fn config_fs_init()->Result<(),()>{    

    if Path::new(&CONFIG_FILE_NAME).exists() {
        //println!("文件已经存在");
        
        match metadata(&CONFIG_FILE_NAME) {
            Ok(_) => Ok(()),
            Err(_) => Err(()),
        }
    } else {
        //println!("文件不存在");
        
        let mut file =  File::create(&CONFIG_FILE_NAME).unwrap();
        let config_struct:Config = Config{
            url : String::from("postgres://postgres:abcd12345@192.168.2.8:5432/fui"),
            sql_type:SqlType::Postgres
        };
        let config_str = serde_json::to_string(&config_struct).unwrap();
        let key = &STR_KEY.as_bytes()[0..32];
        let iv = &STR_KEY.as_bytes()[STR_KEY.as_bytes().len()-16..STR_KEY.as_bytes().len()];
        let encrypted_data = aes256_cbc_encrypt(config_str.as_bytes(), &key, &iv).unwrap();
        match file.write_all(&encrypted_data) {
            Ok(_) => Ok(()),
            Err(_) => Err(()),
        }
    }
}

pub async fn set_config(config:Config)->Result<(),String>{
    println!("进入set_config");
    let mut file = File::create(&CONFIG_FILE_NAME).unwrap();
    println!("打开文件");
    let config_str = serde_json::to_string(&config).unwrap();
    let key = &STR_KEY.as_bytes()[0..32];
    let iv = &STR_KEY.as_bytes()[STR_KEY.as_bytes().len()-16..STR_KEY.as_bytes().len()];
    let encrypted_data = aes256_cbc_encrypt(config_str.as_bytes(), &key, &iv).unwrap();
    println!("开始写入");
    match file.write_all(&encrypted_data) {
        Ok(_) => Ok(()),
        Err(e) => Err(e.to_string())
    }
}

pub async fn get_config() -> Result<Config,String> {
    // 从配置文件中读取数据
    let encrypted_data = match fs::read(&CONFIG_FILE_NAME) {
        Ok(data) => data,
        Err(_) => panic!("无法打开配置文件"),
    };
    let str_key = STR_KEY.to_string(); // 定义一个字符串变量
    let key = &str_key.as_bytes()[0..32];
    let iv = &str_key.as_bytes()[str_key.as_bytes().len()-16..str_key.as_bytes().len()];
    let decrypted_data = aes256_cbc_decrypt(encrypted_data.as_slice(), &key, &iv).unwrap();
    let config_str = String::from_utf8(decrypted_data).unwrap();
    let config:Config = serde_json::from_str(&config_str).unwrap();
    Ok(config)
}

fn aes256_cbc_encrypt(
    data: &[u8],
    key: &[u8],
    iv: &[u8],
) -> Result<Vec<u8>, SymmetricCipherError> {
    let mut encryptor = aes::cbc_encryptor(
        aes::KeySize::KeySize256,
        key, iv,
        blockmodes::PkcsPadding,
    );
 
    let mut buffer = [0; 4096];
    let mut write_buffer = RefWriteBuffer::new(&mut buffer);
    let mut read_buffer = RefReadBuffer::new(data);
    let mut final_result = Vec::new();
 
    loop {
        let result = encryptor.encrypt(&mut read_buffer, &mut write_buffer, true)?;
        final_result.extend(write_buffer.take_read_buffer().take_remaining().iter().map(|&i| i));
        match result {
            BufferUnderflow => break,
            _ => continue,
        }
    }
 
    Ok(final_result)
}
fn aes256_cbc_decrypt(
    data: &[u8],
    key: &[u8],
    iv: &[u8],
) -> Result<Vec<u8>, SymmetricCipherError> {
    let mut decryptor = aes::cbc_decryptor(
        aes::KeySize::KeySize256,
        key, iv,
        blockmodes::PkcsPadding,
    );
 
    let mut buffer = [0; 4096];
    let mut write_buffer = RefWriteBuffer::new(&mut buffer);
    let mut read_buffer = RefReadBuffer::new(data);
    let mut final_result = Vec::new();
 
    loop {
        let result = decryptor.decrypt(&mut read_buffer, &mut write_buffer, true)?;
        final_result.extend(write_buffer.take_read_buffer().take_remaining().iter().map(|&i| i));
        match result {
            BufferUnderflow => break,
            _ => continue,
        }
    }
 
    Ok(final_result)
}


#[test]
fn test_aes256_cbc() {
    config_fs_init();
    let str_key = String::from("HellouiroweuoirujdjdlskjhflajdljafdsfsfsfWorld"); // 定义一个字符串变量
    let key = &str_key.as_bytes()[0..32];
    let iv = &str_key.as_bytes()[str_key.as_bytes().len()-16..str_key.as_bytes().len()];
    let data = "Hello, world!";
    let encrypted_data = aes256_cbc_encrypt(data.as_bytes(), &key, &iv).unwrap();
    let decrypted_data = aes256_cbc_decrypt(encrypted_data.as_slice(), &key, &iv).unwrap();

    let result = String::from_utf8(decrypted_data).unwrap();

    assert_eq!(data, result);
    println!("{}", result);
}